package com.kexio.dynamic.config.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kexio.common.util.JsonUtils;
import com.kexio.dynamic.config.entity.ConfigEntity;
import com.kexio.dynamic.config.repository.ConfigRepository;
import com.kexio.dynamic.config.service.ConfigService;

/**
 * 配置管理服务默认实现
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Service
public class DefaultConfigService extends ServiceImpl<ConfigRepository, ConfigEntity> 
        implements ConfigService {

    private static final Logger log = LoggerFactory.getLogger(DefaultConfigService.class);
    private final ConfigRepository configRepository;
    private final Environment environment;
    
    public DefaultConfigService(ConfigRepository configRepository, Environment environment) {
        this.configRepository = configRepository;
        this.environment = environment;
    }
    
    private static final String DEFAULT_ENVIRONMENT = "dev";
    private static final String CONFIG_CACHE = "config-cache";

    @Override
    @Cacheable(value = CONFIG_CACHE, key = "#key + '_' + getCurrentEnvironment()")
    public String getValue(String key) {
        return getValue(key, getCurrentEnvironment());
    }

    @Override
    public String getValue(String key, String defaultValue) {
        String value = getValue(key);
        return StringUtils.hasText(value) ? value : defaultValue;
    }

    @Override
    @Cacheable(value = CONFIG_CACHE, key = "#key + '_' + #environment")
    public String getValueByEnvironment(String key, String environment) {
        if (!StringUtils.hasText(key)) {
            log.warn("配置键为空");
            return null;
        }

        ConfigEntity config = configRepository.findByKeyAndEnvironment(key, environment);
        if (config == null) {
            log.debug("未找到配置: key={}, environment={}", key, environment);
            return null;
        }

        return config.getConfigValue();
    }

    @Override
    public Integer getIntValue(String key, Integer defaultValue) {
        String value = getValue(key);
        if (!StringUtils.hasText(value)) {
            return defaultValue;
        }
        try {
            return Integer.valueOf(value);
        } catch (NumberFormatException e) {
            log.warn("配置值转换为整数失败: key={}, value={}", key, value, e);
            return defaultValue;
        }
    }

    @Override
    public Long getLongValue(String key, Long defaultValue) {
        String value = getValue(key);
        if (!StringUtils.hasText(value)) {
            return defaultValue;
        }
        try {
            return Long.valueOf(value);
        } catch (NumberFormatException e) {
            log.warn("配置值转换为长整数失败: key={}, value={}", key, value, e);
            return defaultValue;
        }
    }

    @Override
    public Boolean getBooleanValue(String key, Boolean defaultValue) {
        String value = getValue(key);
        if (!StringUtils.hasText(value)) {
            return defaultValue;
        }
        return Boolean.valueOf(value);
    }

    @Override
    public Double getDoubleValue(String key, Double defaultValue) {
        String value = getValue(key);
        if (!StringUtils.hasText(value)) {
            return defaultValue;
        }
        try {
            return Double.valueOf(value);
        } catch (NumberFormatException e) {
            log.warn("配置值转换为双精度失败: key={}, value={}", key, value, e);
            return defaultValue;
        }
    }

    @Override
    public <T> T getJsonValue(String key, Class<T> clazz) {
        String value = getValue(key);
        if (!StringUtils.hasText(value)) {
            return null;
        }
        try {
            return JsonUtils.fromJson(value, clazz);
        } catch (Exception e) {
            log.warn("配置值JSON解析失败: key={}, value={}", key, value, e);
            return null;
        }
    }

    @Override
    @Cacheable(value = CONFIG_CACHE, key = "'group_' + #group + '_' + getCurrentEnvironment()")
    public Map<String, String> getGroupConfigs(String group) {
        if (!StringUtils.hasText(group)) {
            return Collections.emptyMap();
        }

        List<ConfigEntity> configs = configRepository.findByGroupAndEnvironment(group, getCurrentEnvironment());
        return configs.stream()
                .collect(Collectors.toMap(
                    ConfigEntity::getConfigKey,
                    ConfigEntity::getConfigValue,
                    (existing, replacement) -> replacement
                ));
    }

    @Override
    public List<ConfigEntity> getAllConfigs() {
        return configRepository.findAllEnabled(getCurrentEnvironment());
    }

    @Override
    @Cacheable(value = CONFIG_CACHE, key = "'entity_' + #key + '_' + getCurrentEnvironment()")
    public ConfigEntity getConfig(String key) {
        return configRepository.findByKeyAndEnvironment(key, getCurrentEnvironment());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public boolean saveOrUpdate(ConfigEntity config) {
        if (config == null || !StringUtils.hasText(config.getConfigKey())) {
            return false;
        }

        // 设置默认环境
        if (!StringUtils.hasText(config.getEnvironment())) {
            config.setEnvironment(getCurrentEnvironment());
        }

        try {
            return saveOrUpdate(config);
        } catch (Exception e) {
            log.error("保存配置失败: {}", config, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public int batchSave(List<ConfigEntity> configs) {
        if (configs == null || configs.isEmpty()) {
            return 0;
        }

        int successCount = 0;
        for (ConfigEntity config : configs) {
            if (saveOrUpdate(config)) {
                successCount++;
            }
        }
        return successCount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public boolean updateValue(String key, String value) {
        if (!StringUtils.hasText(key)) {
            return false;
        }

        try {
            int updated = configRepository.updateConfigValue(key, value, getCurrentEnvironment());
            return updated > 0;
        } catch (Exception e) {
            log.error("更新配置值失败: key={}, value={}", key, value, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public boolean deleteConfig(String key) {
        if (!StringUtils.hasText(key)) {
            return false;
        }

        try {
            QueryWrapper<ConfigEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("config_key", key)
                   .eq("environment", getCurrentEnvironment());
            return remove(wrapper);
        } catch (Exception e) {
            log.error("删除配置失败: key={}", key, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public boolean toggleConfig(String key, boolean enabled) {
        ConfigEntity config = getConfig(key);
        if (config == null) {
            return false;
        }

        config.setEnabled(enabled);
        return saveOrUpdate(config);
    }

    @Override
    public List<ConfigEntity> getConfigsByTags(String tags) {
        return configRepository.findByTags(tags, getCurrentEnvironment());
    }

    @Override
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public void refreshCache() {
        log.info("刷新配置缓存完成");
    }

    @Override
    @CacheEvict(value = CONFIG_CACHE, allEntries = true)
    public void clearCache() {
        log.info("清空配置缓存完成");
    }

    /**
     * 获取当前环境标识
     */
    private String getCurrentEnvironment() {
        String[] activeProfiles = environment.getActiveProfiles();
        return activeProfiles.length > 0 ? activeProfiles[0] : DEFAULT_ENVIRONMENT;
    }
}
